package com.apes.scm.stock.transfer.service;

import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.Arith;
import com.apes.framework.util.LogicalUtil;
import com.apes.framework.util.MapUtil;
import com.apes.pi.service.PiManager;
import com.apes.scm.account.account.model.AccountingMethod;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.model.InventoryMode;
import com.apes.scm.account.account.service.InventoryService;
import com.apes.scm.account.account.service.StockService;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.service.PartyRoleService;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.sal.saleOrder.SaleOrder;
import com.apes.scm.sal.saleOrder.SaleOrderItem;
import com.apes.scm.sal.saleOrder.SaleOrderRepository;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherInventory;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;
import com.apes.scm.voucher.service.BusinessType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service("pickFlowSaleOrderVoucherService")
public class PickFlowSaleOrderVoucherService extends DomainService {

    @Autowired
    private SaleOrderRepository saleOrderRepository;
    @Autowired
    private VoucherInventoryRepository voucherInventoryRepository;
    @Autowired
    private InventoryService inventoryService;
    @Value("${apes.switched:false}")
    private Boolean switched;

    /**
     * 无库存商品生产采购品，无库存商品和实物商品写一张分销单
     * @param simpleRequest SaleOrder
     * @return Voucher
     */
    public Voucher flowSaleOrderVoucher(SimpleRequest simpleRequest) {
        SaleOrder saleOrder = saleOrderRepository.findOne(simpleRequest.getO(SaleOrder.class).getId());
        if (saleOrder == null) throw new RuntimeException("分销订单不存在！");

        //无实物商品需要先生成采购凭证
        generatePurVoucher(saleOrder);

        Predicate<SaleOrderItem> predicate = (saleOrderItem) -> true;
        // 生成销售凭证
        return createSaleVoucher(saleOrder, predicate);
    }

    /**
     * 无库存商品提前产生销售， 只写无库存商品部分
     * @param simpleRequest SaleOrder
     * @return Voucher
     */
    public Voucher autProductSaleVoucher(SimpleRequest simpleRequest) {
        SaleOrder saleOrder = saleOrderRepository.findOne(simpleRequest.getO(SaleOrder.class).getId());
        if (saleOrder == null) throw new RuntimeException("分销订单不存在！");
        if (saleOrder.getScene() == null) throw new RuntimeException("分销订单对应的场景流错误!");

        //无实物商品需要先生成采购凭证
        generatePurVoucher(saleOrder);

        Predicate<SaleOrderItem> predicate = (saleOrderItem) -> LogicalUtil.in(saleOrderItem.getProduct().getType(), "aut");
        // 无实物商品实现销售
        Voucher voucher = createSaleVoucher(saleOrder, predicate);
        if (voucher.getVoucherItems().isEmpty()) return new Voucher();

        invoke("voucher.create", MapUtil.mapped(voucher));
        return voucher;
    }

    private Voucher createSaleVoucher(SaleOrder saleOrder, Predicate predicate) {
        Voucher voucher = new Voucher();
        // 主表信息
        voucher.setCompany(saleOrder.getCompany());
        voucher.setDept(saleOrder.getDept());
        voucher.setClerk(saleOrder.getClerk()); //业务员
        voucher.setContract(saleOrder.getContract());// 销售合同
        voucher.setPartner(saleOrder.getCustomer());
        voucher.setInventoryMode(saleOrder.getCooperation().getInventoryMode());
        voucher.setAccountingMethod(saleOrder.getCooperation().getAccountingMethod());
        voucher.setScene(saleOrder.getScene());
        voucher.setOrigin(saleOrder.getId());
        voucher.setOriginBusinessType(saleOrder.getInnerBusinessType());
        voucher.setSource(saleOrder.getId());
        voucher.setSourceBusinessType(saleOrder.getInnerBusinessType());

        // 从表信息
        Set<VoucherItem> voucherItems = new HashSet();
        saleOrder.getSaleItems().stream().filter(predicate::test)
                .forEach(
                        item -> {
                            VoucherItem voucherItem = new VoucherItem();
                            voucherItem.setProduct(item.getProduct());
                            voucherItem.setTax(item.getTax());
                            voucherItem.setOwner(saleOrder.getLocation().getCompany());

                            // 设置为销售的单位以及单价
                            voucherItem.setUom(item.getUom());
                            voucherItem.setProductQty(item.getProductUomQty());
                            voucherItem.setPriceUnit(item.getPriceUnit());

                            //分销单取分销佣金
                            if ("FN_SALE".equals(saleOrder.getOrderType())) {
                                double commission = Arith.mul(voucherItem.getProductQty(), getSaleCommission(item.getProduct(), saleOrder.getCompany()));
                                voucherItem.setSaleCommission(commission);
                            }

                            voucherItem.setOriginItemId(item.getId());
                            voucherItem.setSourceItemId(String.valueOf(item.getId()));
                            voucherItem.setSupplier(item.getSupplier());
                            voucherItem.setInventoryBatch(item.getInventoryBatch());    // 如果有批次就指定（服务商品存在批次信息）
                            voucherItems.add(voucherItem);
                        });
        voucher.setVoucherItems(voucherItems);

        return voucher;
    }

    private void generatePurVoucher(SaleOrder saleOrder) {
        Voucher purVoucher = new Voucher();
        purVoucher.setBusinessType(BusinessType.PURCHASE_ORDER);
        purVoucher.setClerk(saleOrder.getClerk()); //业务员

        purVoucher.setDept(SpringManager.getBean(DeptRepository.class)
                .findAll(JpaDsl.toCriteriaByEq("company", saleOrder.getCompany(), "deptType.id", "000006", "valid", true))
                .stream().findFirst().orElseThrow(() -> new RuntimeException(String.format("获取公司 [%s] 的采购部门失败", saleOrder.getCompany().getId()))));
        purVoucher.setCompany(saleOrder.getCompany());
        purVoucher.setPartner(SpringManager.getBean(PartyRoleService.class).findByPartyAndRole(saleOrder.getCompany().getParty().getId(), "Supplier"));
        purVoucher.setCustomerExpand(saleOrder.getFnCustomerExpandId());

        purVoucher.setOrigin(saleOrder.getId());
        purVoucher.setOriginBusinessType(saleOrder.getInnerBusinessType());
        purVoucher.setSource(saleOrder.getId());
        purVoucher.setSourceBusinessType(saleOrder.getInnerBusinessType());
        purVoucher.setInventoryMode(InventoryMode.IM_OWN);
        purVoucher.setAccountingMethod(AccountingMethod.AM_PURCHASE);

        purVoucher.setVoucherItems(
                saleOrder.getSaleItems().stream().filter(item -> LogicalUtil.in(item.getProduct().getType(), "aut"))
                        .map(item -> {
                            VoucherItem voucherItem = new VoucherItem();
                            voucherItem.setProduct(item.getProduct());
                            voucherItem.setOwner(saleOrder.getCompany());

                            // 设置为销售的单位以及数量
                            voucherItem.setUom(item.getUom());
                            voucherItem.setProductQty(item.getProductUomQty());

                            voucherItem.setOriginItemId(item.getId());
                            voucherItem.setSourceItemId(item.getId());

                            voucherItem.setTax(item.getTax());
                            voucherItem.setPriceUnit(0);
                            return voucherItem;
                        }).collect(Collectors.toSet()));

        if (purVoucher.getVoucherItems().size() != 0) {
            purVoucher = invoke("voucher.create", MapUtil.mapped(purVoucher));

            // 回写批次
            backBathAndSupplier(purVoucher);
        }
    }

    private void backBathAndSupplier(Voucher voucher) {
        List lists = voucher.getVoucherItems().stream()
                .map(voucherItem -> {
                    VoucherInventory voucherInventory = voucherInventoryRepository.findByVoucherItem(voucherItem).stream().findAny().orElseThrow(() -> new RuntimeException("找不到批次信息！"));
                    InventoryBatch inventoryBatch = voucherInventory.getInventoryBatch();

                    // 冻结批次
                    inventoryService.changeFrostQty(inventoryBatch, inventoryBatch.getUom(), inventoryBatch.getPurchaseQty(), voucher.getCompany(), voucher.getInnerBusinessType(), voucher.getId(), String.valueOf(voucherItem.getId()), "带安/服务/油漆商品生成分销冻结批次");

                    return MapUtil.mapper("id", voucherItem.getOriginItemId(), "supplierId", voucher.getPartner().getId(), "batchId", inventoryBatch.getId(),
                            "classification", voucher.getClassification(), "priceUint", voucherItem.getPriceUnit());
                }).collect(Collectors.toList());
        sendSynEvent("event:saleOrder.setBatchAndSupplier", MapUtil.mapper("id", voucher.getSource(), "items", lists));
    }

    /**
     * 获取商品的分销佣金
     *
     * @param product 商品
     * @param company 公司
     * @return 佣金
     */
    public double getSaleCommission(Product product, PartyRole company) {
        if (switched) {
            return getNewSaleCommission(product, company);
        } else {
            return getOldSaleCommission(product, company);
        }
    }

    public double getOldSaleCommission(Product product, PartyRole company) {
        Map map = MapUtil.mapper(
                "SPID", product.getId(),
                "PLID", product.getClassify().getId(),
                "PPID", product.getBrand().getId(),
                "JLDW", product.getUom().getName(),
                "SYGSID", SpringManager.getBean(StockService.class).getPlatform(false, true, company, product).getId(),
                "DJGCID", "XS10"
        );
        JSONObject response = SpringManager.getBean(PiManager.class).synErp("ipmVipService.getDjgc", map);
        JSONObject commissionData = JSONObject.parseObject(response.getString("obj"));
        if (!commissionData.containsKey("F061")) {
            throw new RuntimeException("取分销佣金出错，请检分销策略！！！");
        }
        return commissionData.getDoubleValue("F061");
    }

    public double getNewSaleCommission(Product product, PartyRole company) {
        String ptId = SpringManager.getBean(StockService.class).getPlatform(false, true, company, product).getId();

        Map m = MapUtil.mapper(
                "PRODUCT_ID", product.getId(),
                "CLASSIFY_ID", product.getClassify().getId(),
                "BRAND_ID", product.getBrand().getId(),
                "PRODUCT_UOM_ID", product.getUom().getId(),
                "SYS_RQ", new Date(),
                "PUR_COMPANY_ID", ptId,
                "SYS_NO_CHECK", "SUPPLIER_ID",
                "conditionStrategyId","XS10"
        );
        Object obj = invoke("condition.execConditionStrategy", m);
        JSONObject result = new JSONObject(MapUtil.mapped(obj));
        if (!result.containsKey("F061")) {
            throw new RuntimeException("取分销佣金出错，请检分销策略！！！");
        }
        return result.getDoubleValue("F061");
    }

}
